#Boa:Dialog:Transaccion

import wx
import wx.calendar
from wx.lib.anchors import LayoutAnchors
import wx.grid
import consultasBD
import NoCodBarrasEncontrado
import DeseaSalir
import utiles
import TransaccionModificar
import sincronizar_tabla  


def create(parent):
    return Transaccion(parent)

[wxID_TRANSACCION, wxID_TRANSACCIONFECHA, wxID_TRANSACCIONGRID1, 
 wxID_TRANSACCIONGUARDATRANS, wxID_TRANSACCIONINCANTPRODUCTOS, 
 wxID_TRANSACCIONINPTC, wxID_TRANSACCIONNROTRANSFERENCIA, 
 wxID_TRANSACCIONSPINBUTTON1, wxID_TRANSACCIONSTATICTEXT1, 
 wxID_TRANSACCIONSTATICTEXT3, wxID_TRANSACCIONSTATICTEXT4, 
 wxID_TRANSACCIONTXTTRANSFERENCIA, 
] = [wx.NewId() for _init_ctrls in range(12)]

class Transaccion(TransaccionModificar.Transaccion):
    columnas =['Codigo','Descripcion','Talle','Color','Cant.','P. Venta']
    modificables = [0]    
    
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Dialog.__init__(self, id=wxID_TRANSACCION, name='', parent=prnt,
              pos=wx.Point(264, 70), size=wx.Size(595, 483),
              style=wx.DEFAULT_DIALOG_STYLE,
              title='Recepcion de Transacciones')
        self.SetClientSize(wx.Size(587, 456))
        self.Show(True)

        self.staticText3 = wx.StaticText(id=wxID_TRANSACCIONSTATICTEXT3,
              label='Fecha', name='staticText3', parent=self, pos=wx.Point(225,
              2), size=wx.Size(29, 13), style=0)

        self.grid1 = wx.grid.Grid(id=wxID_TRANSACCIONGRID1, name='grid1',
              parent=self, pos=wx.Point(8, 56), size=wx.Size(568, 344),
              style=0)
        self.grid1.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnGrid1CAMBIACELDa)

        self.guardatrans = wx.Button(id=wxID_TRANSACCIONGUARDATRANS,
              label=u'Aceptar', name='guardatrans', parent=self,
              pos=wx.Point(496, 424), size=wx.Size(80, 24), style=0)
        self.guardatrans.Bind(wx.EVT_BUTTON, self.OnGuardatransButton,
              id=wxID_TRANSACCIONGUARDATRANS)

        self.staticText4 = wx.StaticText(id=wxID_TRANSACCIONSTATICTEXT4,
              label='Cant. Productos:', name='staticText4', parent=self,
              pos=wx.Point(8, 408), size=wx.Size(83, 13), style=0)

        self.incantProductos = wx.TextCtrl(id=wxID_TRANSACCIONINCANTPRODUCTOS,
              name='incantProductos', parent=self, pos=wx.Point(8, 424),
              size=wx.Size(64, 21), style=0, value='0')
        self.incantProductos.SetEditable(False)

        self.txttransferencia = wx.StaticText(id=wxID_TRANSACCIONTXTTRANSFERENCIA,
              label='Nro. de Transferencia', name='txttransferencia',
              parent=self, pos=wx.Point(16, 2), size=wx.Size(105, 13), style=0)

        self.nrotransferencia = wx.TextCtrl(id=wxID_TRANSACCIONNROTRANSFERENCIA,
              name='nrotransferencia', parent=self, pos=wx.Point(16, 19),
              size=wx.Size(100, 21), style=0, value='')
        self.nrotransferencia.Bind(wx.EVT_KILL_FOCUS,
              self.OnNro_transferenciaKillFocus)

        self.spinButton1 = wx.SpinButton(id=wxID_TRANSACCIONSPINBUTTON1,
              name='spinButton1', parent=self, pos=wx.Point(131, 20),
              size=wx.Size(72, 17), style=wx.SP_HORIZONTAL)
        self.spinButton1.Bind(wx.EVT_SPIN_UP, self.OnSpinUp,
              id=wxID_TRANSACCIONSPINBUTTON1)
        self.spinButton1.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown,
              id=wxID_TRANSACCIONSPINBUTTON1)

        self.inptc = wx.TextCtrl(id=wxID_TRANSACCIONINPTC, name=u'inptc',
              parent=self, pos=wx.Point(328, 19), size=wx.Size(100, 21),
              style=0, value=u'')
        self.inptc.Bind(wx.EVT_KEY_UP, self.OnInptcKeyUp)
        self.inptc.Bind(wx.EVT_KILL_FOCUS, self.OnInptcKillFocus)

        self.staticText1 = wx.StaticText(id=wxID_TRANSACCIONSTATICTEXT1,
              label='PTC', name='staticText1', parent=self, pos=wx.Point(331,
              2), size=wx.Size(19, 13), style=0)

        self.fecha = wx.TextCtrl(id=wxID_TRANSACCIONFECHA, name='fecha',
              parent=self, pos=wx.Point(224, 19), size=wx.Size(100, 21),
              style=0, value='')

    def __init__(self, parent):
        self._init_ctrls(parent)
        #arma la grilla
        self.padre = parent
        self.fecha.ChangeValue(str(self.padre.fecha))
        
        self.sucursal = self.padre.sucursalNro
        self.columnas =['Codigo','Descripcion','Talle','Color','Restante', 'Cant.','P. Venta']
        self.modificables = []
                    
        self.inptc.SetFocus()
        
        self.cantidad_transferencias = self._cantidad_transferencias()
        if self.cantidad_transferencias == 0:
            utiles.mensaje(self, "No hay Ninguna Transferencia")
            self.Close()        
        
        self.id_transferencia = None
        self.orden_transferencia = 0
                
        self.grillafactura()
        self._cargar_transferencia(self.orden_transferencia)    
        self.items_correctos = self._numero_items()          

    def _mostrar_ptc_en_grilla(self, fila, resultado, stock):
        '''Dado un ptc se muestra en una fila de la grilla'''
        self.grid1.SetCellValue(fila, 0, str(resultado['ptc'])) #descri
        self.grid1.SetCellValue(fila, 1, str(resultado['descri'])) #descri
        self.grid1.SetCellValue(fila, 2, resultado['talle']) #talle
        self.grid1.SetCellValue(fila, 3, resultado['color']) #color
        self.grid1.SetCellValue(fila, 4, "1") #restante
        self.grid1.SetCellValue(fila, 5, "1") #cantidad
        
    def _cargar_transferencia(self, orden_transferencia):
        sql_ultima = self._sql_cargar()
        resultados = consultasBD.ordenCrudaDict(sql_ultima)
        transferencia = resultados[int(orden_transferencia)]
        
        #utiles.cargar_fecha(transferencia['fecha'], self.fechatransferencia)
        
        
        
        
        #
        self.id_transferencia = transferencia['id']                
        self.idsucorigen = transferencia['idsucorigen']
        
        self.nrotransferencia.ChangeValue(str(self.id_transferencia))        
        
        self._limpiar_grilla()
        
        sql_items = self._sql_items()
        items = consultasBD.ordenCrudaDict(sql_items)
        
        cantidad = 0
        for i, item in enumerate(items):            
            stock = self._stock(item['ptc'])
            self._mostrar_ptc_en_grilla(i, item, stock)
            self.grid1.SetCellValue(i, 4, str(item['cant']))
            self.grid1.SetCellValue(i, 5, str(item['cant']))
            self.grid1.SetCellValue(i, 6, str(item['preciolt1']))
            cantidad += item['cant']
            
        self.incantProductos.ChangeValue(str(cantidad))
        
        self._habilitar()
        #if self._es_antigua(self.id_transferencia):
        #    self._deshabilitar()           

    def _sql_cantidad(self):
        return "SELECT count(*) as cantidad FROM transferencias WHERE idsucdestino = '%s' AND estado = 1" % self.sucursal

    def _sql_items(self):
        return "SELECT * FROM transferenciastieneproductos t JOIN producto_talle_color ptc ON (t.ptc = ptc.id) JOIN productos p ON (ptc.codsussan = p.codsussan) WHERE t.idtransferencia = '%s' " % self.id_transferencia         
    
    def _sql_orden(self, idtransferencia):
        return "SELECT * FROM (SELECT *, @row := @row + 1 AS fila FROM transferencias t WHERE idsucdestino = '%s' AND estado = 1 ORDER BY fecha DESC, id DESC) as m WHERE m.id = '%s'" % (self.sucursal, idtransferencia)

    def _sql_cargar(self):
        return "SELECT * FROM transferencias t WHERE idsucdestino = '%s' AND estado = 1 ORDER BY fecha DESC, id DESC " % self.sucursal    

    def _limpiar_grilla(self):        
        for fil in range(self.grid1.GetNumberRows()):
            utiles.colorear_fila(self.grid1, fil, utiles.BLANCO)
            for col in range(6):            
                self.grid1.SetCellValue(fil, col, "")                

    def _numero_items(self):
        result = 0
        for fila in range(self.grid1.GetNumberRows()):
            if self.grid1.GetCellValue(fila,0) == "": 
                break
            result += 1
        return result
    

    def _incrementar_1_cantidad(self, fila):
        '''Dada una fila se incrementa en 1 la cantidad''' 
        cantidad = int(self.grid1.GetCellValue(fila,4)) + 1        
        self.grid1.SetCellValue(fila, 4, str(cantidad))
    
    def _cargar_ptc_extra(self, ptc):
        fila_codigo_repetido = self._fila_codigo_repetido(range(self.items_correctos), ptc)
        if fila_codigo_repetido != None:
            #Esta repetido
            print fila_codigo_repetido
            print "PASO"
            self._incrementar_1_cantidad(fila_codigo_repetido)            
        else:            
            sql = sql = "SELECT *, ptc.id as ptc FROM productos p JOIN producto_talle_color ptc ON(p.codsussan = ptc.codsussan) WHERE ptc.id = '%s'" % ptc
            resultado = consultasBD.ordenCrudaResultDict(sql)
            numero_items = self._numero_items()
            self._mostrar_ptc_en_grilla(numero_items, resultado, 0)
            
            utiles.colorear_fila(self.grid1, numero_items, utiles.ROJO)                      

    def _recibir(self, ptc):  
        for fila in range(self.items_correctos):  
            print "for"          
            if ptc == self.grid1.GetCellValue(fila,0) and self.grid1.GetCellValue(fila,4) != "0":
                restantes = int(self.grid1.GetCellValue(fila,4)) 
                self.grid1.SetCellValue(fila,4, str(restantes - 1))
                
                if restantes == 1:
                    utiles.colorear_fila(self.grid1, fila, utiles.VERDE)                
                
                return
        print "FUERA for"
        self._cargar_ptc_extra(ptc) 
        print "CARGADO"
              
    def _tipo(self, fila):
        '''
        Devuelve 1 si el orden de la fila esta entre la cantidad enviada (Ej. Si se enviaron 5 filas: 1 para la fila 0,1,2,3,4)
                 0 en caso contrario
        '''
        if fila < self.items_correctos:
            return 1
        return 0

    def _crear_discrepancia(self):
        '''
        Inserta registros en la tabla de discrepancias. Habra una discrepancia cuando sobren o falten articulos
        segun la transferencia original
        
        Devuelve 0: No hay discrepancia
                 1: Solo hay Sobrantes
                 2: Solo hay Faltantes
                 3: Hay sobrantes y Faltantes
        '''
        sobra = False
        falta = False
        for fila in range(self.grid1.GetNumberRows()):
            #Si esta todo bien o no tiene nada NO hacer una discrepancia
            if self.grid1.GetCellValue(fila,4) == "0" or self.grid1.GetCellValue(fila,0) == "":
                continue

            ptc  = self.grid1.GetCellValue(fila,0)
            cant = self.grid1.GetCellValue(fila,4)
            tipo = int(self._tipo(fila))

            if tipo == 0:
                sobra = True
            if tipo == 1:
                falta = True

            sql = "INSERT INTO discrepancias (trans, ptc, cant, tipo) VALUES('%s','%s','%s','%s')" % (self.id_transferencia, ptc, cant, tipo)
            sincronizar_tabla.addChange(sql=sql)
            consultasBD.executaSinCommit(None, sql)
        
        if not sobra and not falta: return 0
        if sobra and not falta: return 1
        if not sobra and falta: return 2
        if sobra and falta: return 3

    def _crear_stock_si_no_esta(self, ptc, sucursal):
        '''Retorna el stock que tenga los atrib de parametro, si no esta lo crea'''
        sql = "SELECT * FROM stock WHERE ptc = '%s' AND sucursal = '%s'" % (ptc, self.sucursal)
        resultado = consultasBD.ordenCrudaResultDict(sql)
        if len(resultado) == 0:
            sql_stock = "INSERT INTO stock (ptc, sucursal, stock) VALUES ('%s', '%s', '%s')" %\
            (ptc, sucursal, "0") 
            sincronizar_tabla.addChange(sql=sql_stock)
            consultasBD.executaSinCommit(None, sql_stock)

    def _recibir_stock(self):          
        for fila in range(self.items_correctos):
            restante = int(self.grid1.GetCellValue(fila,4))
            cantidad = int(self.grid1.GetCellValue(fila,5))
            diferencia = cantidad - restante            
            
            ptc  = self.grid1.GetCellValue(fila,0)
            cant = self.grid1.GetCellValue(fila,4)
            
            #Lo llamo para que INSERTE en STOCK si no existe el registro
            self._crear_stock_si_no_esta(ptc, self.sucursal)

            stock = utiles.stock_sumado(ptc, self.sucursal, diferencia)
            sql_change = "UPDATE stock SET stock = '%s' WHERE ptc = '%s' AND sucursal = '%s'" % (stock, ptc, self.sucursal)
            
            utiles.agregar_movimiento(ptc, stock_previo=stock - diferencia, stock_nuevo=stock, operacion='recepcion', idtransferencia = self.id_transferencia, sucursal=self.sucursal)              
            
            sincronizar_tabla.addChange(sql=sql_change)
            consultasBD.executaSinCommit(None, sql_change)           
            
    def _cerrar_transferencia(self):
        sql = "UPDATE transferencias SET estado = '0' WHERE id = '%s'" % self.id_transferencia
        sincronizar_tabla.addChange(sql=sql)
        consultasBD.executaSinCommit(None, sql)

    mensaje_discrepancia = {0: "",
                                 1: '''Se han recepcionado MAS items que los enviados. Comuniquese con la sucursal de origen para solicitar una nueva transferencia de estos items en otro caso deben ser devueltos. Los items con problemas se pueden ver en la seccion de Discrepancias''',
                                 2: '''Sen han recepcionado MENOS items que los enviados. Comuniquese con la sucursal de origen para que ajuste su stock agregando estos items. Los items con problemas se pueden ver en la seccion de Discrepancias''',
                                 3: '''Se han recepcionado MAS items que los enviados de algun producto. Comuniquese con la sucursal de origen para solicitar una nueva transferencia de estos items en otro caso deben ser devueltos. Los items con problemas se pueden ver en la seccion de Discrepancias.
                                 Sen han recepcionado MENOS items que los enviados de algun producto. Comuniquese con la sucursal de origen para que ajuste su stock agregando estos items. Los items con problemas se pueden ver en la seccion de Discrepancias'''}

    def OnGuardatransButton(self, event):
        try:
            consultasBD.begin()
            discrepancia_result = self._crear_discrepancia()
            self._recibir_stock()
            self._cerrar_transferencia()
            consultasBD.commit()
            sincronizar_tabla.syncServerTables(self, ["transferencias", "discrepancias", "stock"])
            utiles.mensaje(self, "La transferencia ha sido Recepcionada")
            if discrepancia_result != 0:
                utiles.mensaje(self, self.mensaje_discrepancia[discrepancia_result])
                
        except sincronizar_tabla.SyncError:
            utiles.mensaje(self, "La transferencia se guardo \n pero no termino de transmitirse por favor realize un sincronizacion")    
        except Exception, e:
            import traceback
            import sys
            exc_type, exc_value, exc_tb = sys.exc_info()
            traceback.print_exception(exc_type, exc_value, exc_tb)
            print e.__str__()
            utiles.mensaje(self, "NO se pudo guardar la transferencia")    
            consultasBD.rollback()
        
        self.Close()
            
    def OnGrid1CAMBIACELDa(self, event):
        event.Skip()

    def OnSalirButton(self, event):
        event.Skip()

    def OnNro_transferenciaKillFocus(self, event):
        event.Skip()

    def OnInptcKeyUp(self, event):
        pass
        
    def OnInptcKillFocus(self, event):
        ptc = self.inptc.Value
        if ptc == "":
            return
        
        self.inptc.SetFocus()
        
        self._recibir(ptc)        
        
        self.inptc.ChangeValue("")         

        event.Skip()
        
    def OnSpinUp(self, event):
        self.orden_transferencia -= 1
        if self.orden_transferencia < 0:
            self.orden_transferencia = self.cantidad_transferencias - 1
        self._cargar_transferencia(self.orden_transferencia)
        self.items_correctos = self._numero_items()
        event.Skip()

    def OnSpinDown(self, event):
        self.orden_transferencia = (self.orden_transferencia + 1) % self.cantidad_transferencias
        self._cargar_transferencia(self.orden_transferencia)
        self.items_correctos = self._numero_items()
        event.Skip()    
        
                   
        
     
                
